﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BackupLib.Targets
{
    using System.IO;

    internal class Filesystem:IBackupTarget
    {
        public virtual string CurrentTargetRoot { get; set; }
        public virtual bool TargetSupportsHardlinks { get; set; }
        public virtual bool TargetSupportsLongNames { get; set; }
        public virtual bool TargetSupportsACL { get; set; }
        public virtual bool TargetSupportsADS { get; set; }
        public virtual bool CopyACL { get; set; }
        public virtual bool CopyADS { get; set; }
        public virtual string SourceRoot { get; set; }
        public virtual string LastTargetRoot { get; set; }
        
        public virtual void BackupFile(string sourceRelative)
        {
            BackupFile(sourceRelative, false);
        }

        public virtual void BackupFile(string sourceRelative, bool noChange)
        {
            string path = PathUtil.GetParentDirectory(CurrentTargetRoot + sourceRelative);
            APIWrapper.CreateDirectory(path);

            if (noChange && TargetSupportsHardlinks)
            {
                try
                {
                    APIWrapper.CreateHardLink(LastTargetRoot + sourceRelative, CurrentTargetRoot + sourceRelative);
                }
                catch (Exception)
                {
                    APIWrapper.CopyFile(true,SourceRoot + sourceRelative, CurrentTargetRoot + sourceRelative);
                }
            }
            else
            {
                APIWrapper.CopyFile(true,SourceRoot + sourceRelative, CurrentTargetRoot + sourceRelative);
            }

            if (APIWrapper.GetFile(CurrentTargetRoot + sourceRelative) == null)
            {
                throw new Exception("target not created");
            }

            if (CopyACL)
            {
                APIWrapper.CopyACL(SourceRoot + sourceRelative, CurrentTargetRoot + sourceRelative);
            }

            ProcessADS(sourceRelative);
        }

        protected virtual void ProcessADS(string sourceRelative)
        {
            if (CopyADS)
            {
                var fsa=APIWrapper.GetADS(CurrentTargetRoot + sourceRelative);
                foreach (KeyValuePair<string,byte[]> stream in fsa)
                {
                    string adsFile = CurrentTargetRoot + sourceRelative + ".ADS." + stream.Key;
                    var fsw = new FileStream(adsFile, FileMode.Create);
                    fsw.Write(stream.Value,0,stream.Value.Length);
                    fsw.Close();
                }
            }
        }

        public virtual void CreateDirectory(string path)
        {
            APIWrapper.CreateDirectory(path);
        }
    }
}
